package blockchain

import (
	"aqchain/pkg/blockchain/contract/license"
	"aqchain/pkg/log"
	"aqchain/pkg/model"
	"context"
	"gitee.com/aqchain/go-ethereum/accounts/abi/bind"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

func (c *Client) SubscribeLicenseContractEvent(ctx context.Context) error {
	createChan := make(chan *license.LicenseContractCreate)
	buyChan := make(chan *license.LicenseContractBuy)
	finishChan := make(chan *license.LicenseContractFinish)
	createSub, err := c.licenseContract.WatchCreate(&bind.WatchOpts{Context: ctx}, createChan, nil)
	if err != nil {
		return err
	}
	defer createSub.Unsubscribe()
	buySub, err := c.licenseContract.WatchBuy(&bind.WatchOpts{Context: ctx}, buyChan, nil, nil)
	if err != nil {
		return err
	}
	defer buySub.Unsubscribe()
	finishSub, err := c.licenseContract.WatchFinish(&bind.WatchOpts{Context: ctx}, finishChan, nil)
	if err != nil {
		return err
	}
	defer finishSub.Unsubscribe()

	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case err = <-createSub.Err():
			return err
		case err = <-buySub.Err():
			return err
		case err = <-finishSub.Err():
			return err
		case event := <-createChan:
			err = c.handleCreateLicense(event)
			if err != nil {
				return err
			}
		case event := <-buyChan:
			err = c.handleBuyLicense(event)
			if err != nil {
				return err
			}
		case event := <-finishChan:
			err = c.handleFinishLicense(event)
			if err != nil {
				return err
			}
		}
	}
}

func (c *Client) handleCreateLicense(event *license.LicenseContractCreate) error {
	block, err := c.client.BlockByHash(context.Background(), event.Raw.BlockHash)
	if err != nil {
		return err
	}
	var itemRecord model.Item
	err = c.db.Where(&model.Item{DCI: event.Dci}).First(&itemRecord).Error
	if err != nil {
		return err
	}
	err = c.db.Transaction(func(tx *gorm.DB) error {
		newLicense := model.License{
			DCI:         event.Dci,
			Seller:      event.Seller.String(),
			BlockNumber: event.Raw.BlockNumber,
			Price:       event.Price.String(),
			Duration:    event.Duration.String(),
			Count:       event.Count.Uint64(),
			BlockTime:   block.Time().Uint64(),
		}
		err = tx.Create(&newLicense).Error
		if err != nil {
			return err
		}
		newEvent := model.LicenseEvent{
			TxHash:      event.Raw.TxHash.String(),
			DCI:         event.Dci,
			From:        event.Seller.String(),
			Value:       event.Price.String(),
			EventName:   "create",
			BlockNumber: event.Raw.BlockNumber,
			BlockTime:   block.Time().Uint64(),
		}
		err = tx.Create(&newEvent).Error
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	log.Logger.Debug("接收到授权交易创建事件", zap.String("DCI", event.Dci), zap.String("Seller", event.Seller.String()), zap.String("Value", event.Price.String()), zap.String("Duration", event.Duration.String()), zap.Uint64("Count", event.Count.Uint64()))
	return nil
}

func (c *Client) handleBuyLicense(event *license.LicenseContractBuy) error {
	block, err := c.client.BlockByHash(context.Background(), event.Raw.BlockHash)
	if err != nil {
		return err
	}
	var itemRecord model.Item
	err = c.db.Where(&model.Item{DCI: event.Dci}).First(&itemRecord).Error
	if err != nil {
		return err
	}
	var licenseRecord model.License
	err = c.db.Where(&model.License{DCI: event.Dci}).First(&licenseRecord).Error
	if err != nil {
		return err
	}
	err = c.db.Transaction(func(tx *gorm.DB) error {
		newLicenseRecord := model.LicenseRecord{
			TxHash:      event.Raw.TxHash.String(),
			RecordID:    event.RecordId.Uint64(),
			DCI:         event.Dci,
			Seller:      licenseRecord.Seller,
			Buyer:       event.Buyer.String(),
			Price:       event.Price.String(),
			CreatedTime: block.Time().Uint64(),
			Deadline:    event.Deadline.Uint64(),
		}
		if licenseRecord.Count == 1 {
			newLicenseRecord.Type = 1
		}
		err = tx.Create(&newLicenseRecord).Error
		if err != nil {
			return err
		}
		newEvent := model.LicenseEvent{
			TxHash:      event.Raw.TxHash.String(),
			DCI:         event.Dci,
			From:        event.Buyer.String(),
			Value:       event.Price.String(),
			EventName:   "buy",
			BlockNumber: event.Raw.BlockNumber,
			BlockTime:   block.Time().Uint64(),
		}
		err = tx.Create(&newEvent).Error
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	log.Logger.Debug("接收到授权交易购买事件", zap.String("DCI", event.Dci), zap.String("Buyer", event.Buyer.String()), zap.String("Value", event.Price.String()))
	return nil
}

func (c *Client) handleFinishLicense(event *license.LicenseContractFinish) error {
	block, err := c.client.BlockByHash(context.Background(), event.Raw.BlockHash)
	if err != nil {
		return err
	}
	var itemRecord model.Item
	err = c.db.Where(&model.Item{DCI: event.Dci}).First(&itemRecord).Error
	if err != nil {
		return err
	}
	var licenseRecord model.License
	err = c.db.Where(&model.License{DCI: event.Dci}).First(&licenseRecord).Error
	if err != nil {
		return err
	}
	err = c.db.Transaction(func(tx *gorm.DB) error {
		err = tx.Delete(&model.License{DCI: event.Dci}).Error
		if err != nil {
			return err
		}
		newEvent := model.LicenseEvent{
			TxHash:      event.Raw.TxHash.String(),
			DCI:         event.Dci,
			From:        licenseRecord.Seller,
			EventName:   "finish",
			BlockNumber: event.Raw.BlockNumber,
			BlockTime:   block.Time().Uint64(),
		}
		err = tx.Create(&newEvent).Error
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	log.Logger.Debug("接收到授权交易结束事件", zap.String("DCI", event.Dci), zap.String("Seller", licenseRecord.Seller))
	return nil
}
